﻿using BattleFury.Data;
using BattleFury.Lib;
using BattleFury.Lib.Controls;
using BattleFury.Lib.Maps;
using BattleFury.Lib.Screens;
using BattleFury.Lib.Tiles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace BattleFury.Screens
{
	public class TestScreen
		: Screen
	{
		#region Fields

		private UserInterface _ui;
		private Console _console;

		public RenderEngine Engine
		{
			get { return RenderEngine.Get(); }
		}

		public BattleFuryWorld World
		{
			get { return RenderData.World; }
		}

		#endregion

		#region Initialization

		public TestScreen()
		{
			World.Camera.Size = RenderEngine.Get().Resolution;
		}

		#endregion

		#region Content

		public override void LoadContent()
		{
			RenderData.LoadFromConfig(Content);

			RenderData.Tilesets.Add("Tileset", new Tileset(Content.Load<Texture2D>(".\\gfx\\Tilesets\\Tileset"), RenderData.TileSize));
			RenderData.Tilesets.Add("DefaultTileset", new Tileset(Content.Load<Texture2D>(".\\gfx\\Tilesets\\DefaultTileset"), RenderData.TileSize));
			RenderData.Tilesets.Add("DefaultDetailTileset", new Tileset(Content.Load<Texture2D>(".\\gfx\\Tilesets\\DefaultDetailTileset"), RenderData.TileSize));

			World.GenerateChunk();

			LoadUserInterface();
		}

		private void LoadUserInterface()
		{
			_ui = new UserInterface();
			_ui.Deserialize(this, ".\\Content\\ui\\default.xaml");
			var clock = (CelestialClock)_ui.GetControl("Clock");
			clock.WorldTime = World.WorldTime;
			_console = (Console)_ui.GetControl("Console");
		}

		#endregion

		#region Update

		public override void Update(Microsoft.Xna.Framework.GameTime gameTime)
		{
			if (!IsEnabled) return;

			UpdateInput();

			_ui.Update(gameTime);

			UpdateBotsAndPlayers(gameTime);

			World.Update(gameTime);
		}

		private void UpdateInput()
		{
			var input = Engine.Input;

			if (input.Keyboard.IsKeyPressed(Keys.Escape)) Engine.Exit();

			if (input.Keyboard.IsKeyPressed(Keys.F1))
			{
				foreach (var bot in RenderData.Bots)
				{
					bot.ShowBounds = !bot.ShowBounds;
				}
				foreach (var player in RenderData.Players)
				{
					player.ShowBounds = !player.ShowBounds;
				}
				if (RenderData.World.CurrentChunk != null)
				{
					foreach (var layer in RenderData.World.CurrentChunk.Layers)
					{
						if (layer is CollisionLayer)
						{
							layer.IsVisible = !layer.IsVisible;
						}
					}
				}
			}
			
			//if (input.Keyboard.IsKeyPressed(Keys.F2)) LoadMap();
			//if (input.Keyboard.IsKeyPressed(Keys.F3)) LoadTiledMap();
			//if (input.Keyboard.IsKeyPressed(Keys.F4)) ToggleViewRange();
			//if (input.Keyboard.IsKeyPressed(Keys.F7)) RenderEngine.Get().NetworkClient.Connect();
			//if (input.Keyboard.IsKeyPressed(Keys.F8)) RenderEngine.Get().NetworkClient.Disconnect();
			//if (input.Keyboard.IsKeyPressed(Keys.F9)) _showWorldVisualization = !_showWorldVisualization;
			//if (input.Keyboard.IsKeyPressed(Keys.F10)) GenerateWorld();


			if (input.Keyboard.IsKeyHeld(Keys.Up)) World.Camera.Move(new Vector2(0f, -RenderData.CameraSpeed));
			if (input.Keyboard.IsKeyHeld(Keys.Down)) World.Camera.Move(new Vector2(0f, RenderData.CameraSpeed));
			if (input.Keyboard.IsKeyHeld(Keys.Left)) World.Camera.Move(new Vector2(-RenderData.CameraSpeed, 0f));
			if (input.Keyboard.IsKeyHeld(Keys.Right)) World.Camera.Move(new Vector2(RenderData.CameraSpeed, 0f));
		}

		private void UpdateBotsAndPlayers(GameTime gameTime)
		{
			foreach (var player in RenderData.Players)
			{
				player.Update(gameTime);
			}

			foreach (var bot in RenderData.Bots)
			{
				bot.Update(gameTime);
			}
		}

		#endregion

		#region Draw

		public override void Draw(GameTime gameTime)
		{
			if (!IsVisible) return;

			Engine.GraphicsDevice.Clear(Color.Black);

			SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.AnisotropicClamp, null, null, null, World.Camera.Matrix);

				if (RenderData.Errors.Count > 0)
				{
					DrawErrors();
				}
				else
				{
					DrawScreen(gameTime);
				}

			SpriteBatch.End();

			DrawUserInterface(gameTime);

			base.Draw(gameTime);
		}

		private void DrawErrors()
		{
			var line = 0;
			var font = OldRenderData.Fonts["Default"];
			foreach (var error in OldRenderData.Errors)
			{
				SpriteBatch.DrawString(font, error, new Vector2(8, line), Color.Red);
				line += 32;
			}
		}

		private void DrawScreen(GameTime gameTime)
		{
			DrawUnderlayer(gameTime);

			foreach (var player in RenderData.Players)
			{
				player.Draw(gameTime);
			}

			foreach (var bot in RenderData.Bots)
			{
				bot.Draw(gameTime);
			}

			DrawOverlayer(gameTime);

			var lightLayer = ((TileMap) World.CurrentChunk).GetLayer("Lights");
			if (lightLayer != null)
			{
				SpriteBatch.End();
				lightLayer.Draw(gameTime, SpriteBatch);
				SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.AnisotropicClamp, null, null, null, World.Camera.Matrix);
			}
		}

		private void DrawUnderlayer(GameTime gameTime)
		{
			var map = (TileMap)World.CurrentChunk;
			map.DrawLayer("Ground", gameTime, SpriteBatch);
			map.DrawLayer("Detail", gameTime, SpriteBatch);
		}

		private void DrawOverlayer(GameTime gameTime)
		{
			var map = (TileMap)World.CurrentChunk;
			map.DrawLayer("Overlay", gameTime, SpriteBatch);
			map.DrawCollisionLayer("Collisions", gameTime, SpriteBatch);
		}

		private void DrawUserInterface(GameTime gameTime)
		{
			_ui.Draw(gameTime);
		}

		#endregion
	}
}